<template>
    <div style="padding: 0 1rem" v-loading="loading">
        <div class="global-search-main">
            <div class="global-search-wrapper">
                <el-autocomplete v-model="area.value" :fetch-suggestions="querySearchAsync"
                                 class="global-search"
                                 clearable
                                 placeholder="请输入城市名称, 例如: 北京, 上海"
                                 highlight-first-item
                                 @select="onSelect">
                    <template #default="{ item }">
                        <div class="name">{{ item.value }}</div>
                    </template>
                </el-autocomplete>
            </div>
        </div>
        <div class="current-weather">
            <el-card>
                <template #header>
                    <div class="clearfix">
                        <el-button style="padding: 3px 0" text>
                            <template #icon>
                                <el-icon>
                                    <Location />
                                </el-icon>
                            </template>
                            {{weather.provinceName}}-{{ weather.countyName }}
                        </el-button>
                        <el-button style="float: right; padding: 3px 0" text @click="searchWeather">
                            <template #icon>
                                <el-icon>
                                    <Refresh />
                                </el-icon>
                            </template>
                        </el-button>
                    </div>
                </template>
                <el-row>
                    <el-col :span="20">
                        <div class="current-weather__main" style="">
                            <p style="display: inline-block;font-size: 86px;height: 86px;line-height: 86px;margin-right: 24px;">
                                {{ weather.realtime['temp'] }}℃
                            </p>
                            <p style="display: inline-block;font-size: 28px;line-height: 45px;height: 45px;margin-right: 24px;">
                                {{ weather.realtime['weather'] }}
                            </p>
                            <div :class="`air air-level${weather.pm25['level']}`">
                                <el-popover :title="`空气质量指数&nbsp;&nbsp;${weather.pm25['aqi']}&nbsp;&nbsp;${weather.pm25['quality']}`"
                                            :width="255"
                                            :teleported="false"
                                            placement="right"
                                            popper-style="padding: 0;">
                                    <template #reference>
                                        <p class="info-aqi">
                                            空气质量&nbsp;{{ weather.pm25['aqi'] }}&nbsp;&nbsp;{{ weather.pm25['quality'] }}
                                        </p>
                                    </template>
                                    <template #default>
                                        <table class="aqi-table">
                                            <tbody>
                                            <tr>
                                                <th>
                                                    <p class="val">{{ weather.pm25['pm25'] }}</p>
                                                    <p class="title">PM2.5</p>
                                                </th>
                                                <th>
                                                    <p class="val">{{ weather.pm25['pm10'] }}</p>
                                                    <p class="title">PM10</p>
                                                </th>
                                                <th>
                                                    <p class="val">{{ weather.pm25['so2'] }}</p>
                                                    <p class="title">SO2</p>
                                                </th>
                                            </tr>
                                            <tr>
                                                <th>
                                                    <p class="val">{{ weather.pm25['no2'] }}</p>
                                                    <p class="title">NO2</p>
                                                </th>
                                                <th>
                                                    <p class="val">{{ weather.pm25['o3'] }}</p>
                                                    <p class="title">O3</p>
                                                </th>
                                                <th>
                                                    <p class="val">{{ weather.pm25['co'] }}</p>
                                                    <p class="title">CO</p>
                                                </th>
                                            </tr>
                                            </tbody>
                                        </table>
                                    </template>
                                </el-popover>
                            </div>
                            <div :class="`alarm-tag alarm-level${alarm['alarmLevelNo']}`" v-for="(alarm, index) in weather.alarms" :key="index">
                                <el-popover :title="`${alarm['alarmTypeDesc'].replace('预警', alarm['alarmLevelNoDesc'])}预警`"
                                            :width="255"
                                            :teleported="false"
                                            placement="right"
                                            popper-style="padding: 0;">
                                    <template #reference>
                                        <p class="alarm-type">
                                            {{ alarm['alarmTypeDesc'] }}
                                        </p>
                                    </template>
                                    <template #default>
                                        <div class="context">
                                                    <span>
                                                        {{ alarm['alarmContent'] }}
                                                    </span>
                                        </div>
                                    </template>
                                </el-popover>

                            </div>
                        </div>
                        <div class="ct-other">
                            <p class="item">
                                <el-icon :size="20">
                                    <svg-icon name="el-icon-position"/>
                                </el-icon>
                                <span class="txt" style="display: inline-block;font-size: 18px;vertical-align: middle;">
                                            {{ weather.realtime['wD'] }}&nbsp;{{ weather.realtime['wS'] }}
                                        </span>
                            </p>
                            <p class="item">
                                <el-icon :size="20">
                                    <svg-icon name="Humidity"/>
                                </el-icon>
                                <span class="txt">湿度&nbsp;{{ weather.realtime['sD'] }}%</span>
                            </p>
                            <p class="item">
                                <el-icon :size="20">
                                    <svg-icon name="SendibleTemp"/>
                                </el-icon>
                                <span class="txt" id="txt-kPa">体感温度&nbsp;{{ weather.realtime['sendibleTemp'] }}℃</span>
                            </p>
                        </div>
                        <div>
                            <p>更新时间：{{ weather.realtime.time }}</p>
                        </div>
                    </el-col>
                    <el-col :span="4" style="display: flex; justify-content: center; align-items: center;">
                        <el-image
                                style="width: 135px; height: 135px"
                                :src="`https://mat1.gtimg.com/pingjs/ext2020/weather/pc/icon/currentweather/day/${(Number(weather.realtime['img']) < 10?'0':'') + weather.realtime['img']}.png`"
                                :zoom-rate="1.2"
                                :max-scale="7"
                                :min-scale="0.2"
                                :initial-index="4"
                                fit="cover"
                        />
                    </el-col>
                </el-row>

            </el-card>
        </div>
        <el-row :gutter="20">
            <el-col :span="12" >
                <el-card body-style="background-color: var(--el-color-primary-light-9)">
                    <div id="temperature" style="height: 405px"/>
                </el-card>
            </el-col>
            <el-col :span="12" >
                <div class="weather-area">
                    <div class="weather-info">
                        <el-card body-style="height: 350px">
                            <template #header>
                                <div class="clearfix">
                                    <span>生活指数</span>
                                </div>
                            </template>
                            <el-row>
                                <el-col v-for="(i, index) in weather.indexes" :key="index" :span="24">
                                    <p>{{ i.name }} --- {{ i.content }}</p>
                                </el-col>
                            </el-row>
                        </el-card>
                    </div>
                </div>
            </el-col>
        </el-row>
    </div>
</template>
<script lang="ts" setup>
import {computed, markRaw, onMounted, onUnmounted, reactive, ref, toRaw} from 'vue';
import {service, dateFormat} from '@/utils';
import {cities as cityData} from './city';
import {useEchartsTheme} from '@/utils';
import * as echarts from 'echarts';
import { EChartsType } from 'echarts'
import {Location, Refresh} from "@element-plus/icons-vue";
import { ElMessage } from 'element-plus';

interface City {
    code: string
    value: string
}

interface Weather {
    provinceName: string;
    countyName: string;
    weathers: string[],
    images: string[],
    days: number[],
    nights: number[],
    hours: number[],
    dateArr: string[],
    timeArr: string[],
    weeks: string[],
    publishTime: string,
    alarms: any[],
    realtime: {[key:string]:any},
    indexes: {[key:string]:any}[],
    pm25: {[key:string]:any},
}

const today = dateFormat(new Date(), 'yyyy-MM-dd');
const city = computed<any>({
    get: () => {
        return localStorage.getItem('city') || undefined;
    },
    set: (value: any) => {
        localStorage.setItem('city', JSON.stringify(value));
    }
});
const loading = ref(false);
const weather = reactive<Weather>({
    provinceName: '',
    countyName: '',
    weathers: [],
    images: [],
    days: [],
    nights: [],
    hours: [],
    dateArr: [],
    timeArr: [],
    weeks: [],
    publishTime: '',
    alarms: [],
    realtime: {},
    indexes: [],
    pm25: {},
});
const cities = ref<City[]>(cityData)
const area = ref<City>({
    value: '',
    code: ''
});

const querySearchAsync = (queryString: string, cb: (arg: any) => void) => {
    let results = queryString? cities.value.filter(createFilter(queryString)) : cities.value;
    cb(results);
};

const createFilter = (queryString: string) => {
    return (item: City) => item.value.indexOf(queryString) === 0;
};

const onSelect = (value: any) => {
    city.value = value;
    searchWeather(value);
}

const future = ref<EChartsType>(); // 获取echarts
const option = reactive<{[key:string]:any}>({
    title: {
        text: '7日天气预报'
    },
    grid: {
        height: 350,
        show: true,
        backgroundColor: 'transparent',
        opacity: 0.3,
        borderWidth: '0',
        top: 240,
    },
    tooltip: {
        trigger: 'axis',
        formatter: "{b}<br/>{a}: {c}°C <br/>{a1}: {c1}°C"
    },
    legend: {
        data: ['日间气温', '夜间气温']
    },
    toolbox: {
        show: true,
        feature: {
            mark: {show: true},
            dataView: {show: true, readOnly: false},
            magicType: {show: false, type: ['line', 'bar']},
            restore: {show: true},
            saveAsImage: {show: true}
        }
    },
    calculable: true,
    xAxis: [
        {
            type: 'category',
            boundaryGap: false,
            position: 'top',
            offset: 160,
            zlevel: 100,
            data: ['周期'],
            axisLine: {
                show: false, // 去掉X轴线
            },
            axisTick: {
                show: false, // 去掉X轴线间隔符
            },
            axisLabel: {
                interval: 0,
                formatter: ['{a|{value}}'].join('\n'),
                rich: {
                    a: {

                        fontSize: 14,
                    },
                },
            },
        },
        {
            type: 'category',
            boundaryGap: false,
            position: 'top',
            offset: 140,
            zlevel: 100,
            axisLine: {
                show: false,
            },
            axisTick: {
                show: false,
            },
            axisLabel: {
                interval: 0,
                formatter: ['{a|{value}}'].join('\n'),
                rich: {
                    a: {
                        color: 'var(--el-text-color-primary);',
                        fontSize: 12,
                    },
                },
            },
            data: ['日期'],
        },
        {
            type: 'category',
            boundaryGap: false,
            position: 'top',
            offset: 40,
            zlevel: 100,
            axisLine: {
                show: false,
            },
            axisTick: {
                show: false,
            },
            axisLabel: {
                interval: 0,
                formatter: function (value: any, index: any) {
                    return '{b|' + value + '}\n{' + index + '| }'
                },
                rich: {
                    b: {
                        color: 'var(--el-text-color-primary);',
                        fontSize: 12,
                        lineHeight: 30,
                        height: 20,
                    },
                },
            },
            data: ['天气'],
        },
    ],
    yAxis: [
        {
            show: false,
            type: 'value',
            axisLabel: {
                show: false,
                formatter: '{value} °C'
            }
        }
    ],
    series: [
        {
            name: '日间气温',
            type: 'line',
            data: [11, 11, 15, 13, 12, 13, 10],
            label: {
                show: true,
                position: 'top',
                formatter: (v: any) => {
                    return v.data + ' °C'
                },
            },
            markLine: {
                data: [
                    {type: 'average', name: '平均值'}
                ]
            },
        },
        {
            name: '夜间气温',
            type: 'line',
            data: [1, -2, 2, 5, 3, 2, 0],
            label: {
                show: true,
                position: 'bottom',
                formatter: (v: any) => {
                    return v.data + ' °C'
                }
            },
            markLine: {
                data: [
                    {type: 'average', name: '平均值'}
                ]
            }
        }
    ]
});

const searchWeather = (area: any) => {
    if (area.code) {
        loading.value = true;
        service.get('/weather', {areaId: area.code}).then(({data}) => {
            if (data.code === '200') {
                weather.provinceName = data.value[0]['provinceName'];
                weather.countyName = data.value[0]['city'];
                weather.alarms = data.value[0]['alarms'];
                weather.realtime = data.value[0]['realtime'];
                weather.indexes = data.value[0]['indexes'];
                weather.pm25 = data.value[0]['pm25'];
                weather.pm25['level'] = getAirLevel(weather.pm25['aqi'])

                weather.weeks = []; weather.days = []; weather.nights = []; weather.dateArr = []; weather.weathers = []; weather.images = [];
                let weathers = data.value[0].weathers;
                for (let i = 0; i < weathers.length; i++) {
                    let current = weathers[i];
                    if (i === weathers.length - 1) {
                        weather.weeks.unshift('昨天');
                        weather.days.unshift(parseFloat(current['temp_day_c']));
                        weather.nights.unshift(parseFloat(current['temp_night_c']));
                        weather.dateArr.unshift(current['date'].substring(5));
                        weather.weathers.unshift(current['weather']);
                        weather.images.unshift(current['img']);
                    } else {
                        weather.weeks.push(current.date === today ? '今天' : current.week);
                        weather.days.push(parseFloat(current['temp_day_c']));
                        weather.nights.push(parseFloat(current['temp_night_c']));
                        weather.dateArr.push(current['date'].substring(5));
                        weather.weathers.push(current['weather']);
                        weather.images.push(current['img']);
                    }
                }
                option.xAxis[0].data = weather.weeks;
                option.xAxis[1].data = weather.dateArr;
                option.xAxis[2].data = weather.weathers;
                option.series[0].data = weather.days;
                option.series[1].data = weather.nights;

                weather.images.reduce((obj: any, image: string, index: number) => {
                    obj[index] = {
                        backgroundColor: {image: `https://mat1.gtimg.com/pingjs/ext2020/weather/pc/icon/weather/day/${(Number(image) <= 9 ? '0' : '') + image}.png`},
                        height: 40,
                        width: 40,
                    }
                    return obj
                }, option.xAxis[2].axisLabel.rich);

                const details = data.value[0]['weatherDetailsInfo'];
                weather.publishTime = details['publishTime'];
                const weather3HoursDetailsInfos = details['weather3HoursDetailsInfos'];
                for (let i = 0; i < weather3HoursDetailsInfos.length; i++) {
                    let time = weather3HoursDetailsInfos[i].endTime.split(' ')[1].split(':');
                    weather.hours.push(parseFloat(weather3HoursDetailsInfos[i]['highestTemperature']));
                    weather.timeArr.push(time[0] + ':' + time[1]);
                }

                toRaw(future.value)?.setOption(option);
            } else {
                ElMessage.error(data.message);
            }
            loading.value = false;
        });
    }
};

const getAirLevel = (aqi: number): number => {
    return aqi > 300? 6 : aqi > 200? 5 : aqi > 150? 4 : aqi > 100? 3 : aqi > 50? 2 : 1;
}

const onReset = () => {
    future.value?.resize(); // 窗口发生改变就更新echarts
}
const {macarons} = useEchartsTheme();
onMounted(() => {
    echarts.registerTheme('theme', macarons)
    future.value = markRaw(echarts.init(document.getElementById('temperature'), "theme"));

    if (city.value !== undefined) {
        area.value = JSON.parse(city?.value);
        searchWeather(area.value);
    }

    window.addEventListener("resize", onReset);
});

onUnmounted(() => {
    // 卸载echarts实例
    future.value?.dispose();
    window.removeEventListener("resize", onReset);
});
</script>

<style lang="scss" scoped>
.current-weather {
    margin-bottom: 28px;

    .current-weather__main {
        height: 86px;
        vertical-align: bottom;
        font-size: 0;

        .air {
            display: inline-block;
            position: relative;
            margin-right: 24px;
            cursor: pointer;

            p {
                display: flex;
                justify-content: center;
                align-items: center;
                border-radius: 18px;
                height: 18px;
                line-height: 18px;
                font-size: 14px;
                padding: 3px 10px;
            }

            &.air-level1 {
                .info-aqi,
                ::v-deep(.el-popover__title) {
                    background-color: #a3d765
                }
            }

            &.air-level2 {
                .info-aqi,
                ::v-deep(.el-popover__title) {
                    background-color: #f0cc35
                }
            }

            &.air-level3 {
                .info-aqi,
                ::v-deep(.el-popover__title) {
                    background-color: #f1ab62
                }
            }

            &.air-level4 {
                .info-aqi,
                ::v-deep(.el-popover__title) {
                    background-color: #ef7f77
                }
            }

            &.air-level5 {
                .info-aqi,
                ::v-deep(.el-popover__title) {
                    background-color: #b28ccb
                }
            }

            &.air-level6 {
                .info-aqi,
                ::v-deep(.el-popover__title) {
                    background-color: #ad788a
                }
            }

            ::v-deep(.el-popover__title) {
                padding: 20px 10px;
                text-align: center;
                margin-bottom: 0;
            }
        }

        .aqi-table {
            width: 100%;
            height: 100%;

            tr:first-child {
                th {
                    border-bottom: 1px solid var(--el-border-color);
                }
            }

            tr {
                height: 65px;

                .val {
                    font-size: 14px;
                    line-height: 24px;
                }

                .title {
                    font-size: 12px;
                    color: #9f9f9f;
                    line-height: 24px;
                }

                th {
                    width: 85px;
                }

                th:nth-child(2) {
                    border-right: 1px solid var(--el-border-color);
                    border-left: 1px solid var(--el-border-color);
                }
            }
        }

        .alarm-tag {
            border-radius: 18px;
            font-size: 14px;
            display: inline-block;
            height: 24px;
            line-height: 24px;
            padding: 0 12px;
            margin-right: 5px;
            cursor: pointer;
            position: relative;

            p {
                display: flex;
                align-items: center;
                border-radius: 18px;
                height: 18px;
                line-height: 18px;
                font-size: 14px;
                padding: 3px 10px 3px 10px;
            }

            .context {
                padding: 14px 20px 5px;
                font-size: 14px;
                line-height: 24px;
            }

            &.alarm-level01 {
                .alarm-type,
                ::v-deep(.el-popover__title) {
                    background-color: #86c5f7
                }
            }


            &.alarm-level02 {
                .alarm-type,
                ::v-deep(.el-popover__title) {
                    background-color: #f5d271
                }
            }

            &.alarm-level03 {
                .alarm-type,
                ::v-deep(.el-popover__title) {
                    background-color: #ef8c6b
                }
            }

            &.alarm-level04 {
                .alarm-type,
                ::v-deep(.el-popover__title) {
                    background-color: #ec807c
                }
            }

            ::v-deep(.el-popover__title) {
                padding: 20px 10px;
                text-align: center;
                margin-bottom: 0;
            }
        }
    }

    .ct-other {
        vertical-align: middle;
        font-size: 0;
        margin-bottom: 28px;

        .item {
            display: inline-block;
            margin-right: 42px;
            height: 20px;
            line-height: 20px;
            font-size: 0;

            i {
                display: inline-block;
                height: 20px;
                width: 20px;
                background-size: 20px 20px;
                vertical-align: middle;
                margin-right: 10px;
            }
        }

        .txt {
            display: inline-block;
            font-size: 18px;
            vertical-align: middle;
        }
    }
}
</style>

<style lang="scss" scoped>
.my-autocomplete {
    li {
        line-height: normal;
        padding: 7px;

        .name {
            text-overflow: ellipsis;
            overflow: hidden;
        }

        .addr {
            font-size: 12px;
            color: #b4b4b4;
        }

        .highlighted .addr {
            color: #ddd;
        }
    }
}

.global-search-main {
    margin-top: 1.5rem;
    margin-bottom: 1.5rem;

    .global-search-wrapper {
        width: 350px;
        margin: 0 auto;

        .global-search {
            width: 100%;
        }
    }
}

.weather-area {
    display: inline;

    .weather-chart-info {
        width: 60%;
        display: inline-block;

        .chart-box {
            min-height: 400px;
        }
    }

    .weather-info {
        width: 100%;
        display: inline-block;

        p {
            margin-bottom: .4rem !important;
        }
    }
}
</style>
